package ifmo.is.lab1;

import java.util.AbstractCollection;
import java.util.Arrays;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.NoSuchElementException;

/**
 * 
 * ArrayList
 * @author Anton
 *
 */

public class MyList extends AbstractCollection<Integer>{
	private Integer[] array;
	private int size=0;
	/**
	 * Constructor
	 * Create zeros ArrayList
	 */
	public MyList()
	{
		this.array = new Integer[0];
	}
	/**
	 * Check ranges in array
	 * @param index Index in Array for check
	 * @throws ArrayIndexOutOfBoundsException
	 */
	private void check(int index)
	{
		if(index < 0 || index > this.size()) throw new ArrayIndexOutOfBoundsException("Out of bound");
	}
	/**
	 * Appends the specified element to the end of this list.
	 * @param x Integer value for insert in List
	 * @return true
	 */
	public boolean add(Integer x)
	{
		if(this.array.length==this.size())
		{
			this.resize(this.array,(this.size()*2)+1);
		}
		this.array[this.size()] = x;	
		this.size++;
		return true;
	}
	/**
	 * Remove all elements with value x
	 * @param x Integer value
	 * @return true
	 */
	public boolean removeFromCell(int x)
	{
		for(int i=0;i<this.size(); i++)
		{
			if(this.array[i].equals(x))
			{
				this.remove(i);
			}
		}
		return true;
	}
	/**
	 * Removes the element at the specified position in this list.
	 * @return the element that was removed from the list
	 */
	public Integer remove(int index)
	{
		check(index);
		Integer r = array[index];
		if(index+1 != this.size())
		{
			for(int i = index; i<this.size()-1; i++)
			{
				this.array[i]=this.array[i+1];
			}
		}
		this.array[this.size()-1]=null;
		this.size--;
		return r;
	}
	/**
	 * Returns the element at the specified position in this list.
	 * @return element value
	 */
	public Integer get(int index)
	{
		check(index);
		return this.array[index];
	}
	/**
	 * Returns true if this list contains no elements.
	 * @return boolean. True if this list contains no elements.
	 */
	@Override
	public boolean isEmpty()
	{
		if(this.size()==0) return true;
		return false;
	}
	/**
	 * Return array size
	 * @return int - size array
	 */
	@Override
	public int size() 
	{
		return this.size;
	}
	/**
	 * Removes all of the elements from this list. The list will be empty after this call returns.
	 */
	@Override
	public void clear()
	{
		int sizearr = this.size();
		for(int i=0; i<sizearr;i++)
		{
			this.array[i] = null;
			this.size--;
		}
	}
	/**
	 * Returns the index of the first occurrence of the specified element in this list, or -1 if this list does not contain the element.
	 * @param x element to search for
	 * @return the index of the first occurrence of the specified element in this list, or -1 if this list does not contain the element
	 */
	public int indexOf(int x)
	{
		for(int i=0;i<this.size();i++)
		{
			if(this.array[i]==x) return i;
		}
		return -1;
	}
	/**
	 * Resize array
	 * @param source array
	 * @param newLength new length array
	 */
	public void resize(Integer[] source, int newLength)
	{
		this.array = Arrays.copyOf(source, newLength);
	}
	/**
	 * Returns a string representation of this collection. 
	 * @return a string representation of this collection. 
	 */
    public String toString() 
    {
        /*String result="";
        for(int i=0;i<size;i++)
        	result+=get(i)+" ";
        return result;*/
    	return super.toString();
    }
	public ListIterator<Integer> iterator() 
	{
		return new MyIterator();
	}
	public class MyIterator implements ListIterator<Integer>
	{
		int it = -1;
		public boolean hasNext() 
		{
			if(MyList.this.size()!=it+1) return true;
			return false;
		}
		public boolean hasPrevious() 
		{
			if(it == -1) return false;
			return true;
		}
		public Integer previous() 
		{
			if(!this.hasPrevious()) throw new NoSuchElementException("Out of bound");
			//this.it++;
			return MyList.this.get(this.it--);
		}
		public Integer next() 
		{
			if(!this.hasNext()) throw new NoSuchElementException("Out of bound");
			//this.it++;
			return MyList.this.get(++this.it);
		}
		public void remove() 
		{
			throw new UnsupportedOperationException();
			
		}
		@Override
		public int nextIndex() 
		{
			throw new UnsupportedOperationException();
		}
		@Override
		public int previousIndex() 
		{
			throw new UnsupportedOperationException();
		}
		@Override
		public void set(Integer e) 
		{
			throw new UnsupportedOperationException();
			
		}
		@Override
		public void add(Integer e) 
		{
			throw new UnsupportedOperationException();
		}
	}

}
